package com.cxyjy.travelguide.service.Impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cxyjy.common.BusinessException;
import com.cxyjy.common.pojo.PageResult;
import com.cxyjy.common.util.HttpUtils;
import com.cxyjy.common.util.JFileUtil;
import com.cxyjy.common.util.JObjectUtil;
import com.cxyjy.travelguide.controller.vo.ArtifactCreateVO;
import com.cxyjy.travelguide.controller.vo.ArtifactQueryVO;
import com.cxyjy.travelguide.controller.vo.ArtifactRespVO;
import com.cxyjy.travelguide.dal.dataobject.ExternalArtifactDO;
import com.cxyjy.travelguide.dal.dataobject.ExternalBaiduAiImageDO;
import com.cxyjy.travelguide.entity.ExternalArtifact;
import com.cxyjy.travelguide.entity.ExternalBaiduAiImage;
import com.cxyjy.travelguide.mapper.ExternalArtifactMapper;
import com.cxyjy.travelguide.mapper.ExternalBaiduAiImageMapper;
import com.cxyjy.travelguide.service.ArtifactService;
import com.cxyjy.travelguide.service.BaiduAiImageService;
import com.cxyjy.travelguide.service.TemplateImageService;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.cxyjy.common.constants.ImageMatchConstants.*;
import static com.cxyjy.common.util.JObjectUtil.isEmpty;
import static com.cxyjy.common.util.JObjectUtil.stringValue;

/**
 * @Author: jony
 * @Date : 2025/4/29 16:29
 * @VERSION v1.0
 */
@Slf4j
@Service("TemplateImageService")
public class TemplateImageServiceImpl implements TemplateImageService {
    @Autowired
    private ArtifactService artifactService;
    @Autowired
    private BaiduAiImageService baiduAiImageService;


    @Autowired
    private ExternalBaiduAiImageMapper baiduAiImageMapper;
    @Autowired
    private ExternalArtifactMapper artifactMapper;

    @Override
    public Map<String, Object> uploadTemplateImage(MultipartFile image, String objectCode, String objectName, String classId1, String classId2) throws Exception {
        Map<String, Object> resultMap = new HashMap<>();
        // 验证文件扩展名
        String fileName = image.getOriginalFilename();
        if (!JObjectUtil.isLong(classId1) || !JObjectUtil.isLong(classId2)) {
            resultMap.put("error", 10011);
            return resultMap;
        }

        if (fileName == null || !fileName.contains(".")) {
            resultMap.put("error", 10000);
            return resultMap;
        }
        // 将图片文件转换成Base64编码
        String imageBase64 = JFileUtil.convertToBase64(image);
        // URL编码Base64数据
        String encodedImage = URLEncoder.encode(imageBase64, StandardCharsets.UTF_8.toString());
        String requestBody = "rn=100&image=" + encodedImage + "&brief=" + objectCode + "&tags=" + classId1 + "," + classId2;
        return uploadImageToBaidu(requestBody, objectCode, objectName, classId1, classId2);
    }

    @Override
    public Map<String, Object> uploadTemplateImage(String imageUrl, String objectCode, String objectName, String classId1, String classId2) throws IOException {
        Map<String, Object> resultMap = new HashMap<>();
        if (!JObjectUtil.isLong(classId1) || !JObjectUtil.isLong(classId2)) {
            resultMap.put("error", 10011);
            return resultMap;
        }
        if (!JFileUtil.isImageUrl(imageUrl)) {
            resultMap.put("error", 10000);
            return resultMap;
        }
        String requestBody = "rn=100&url=" + URLEncoder.encode(imageUrl, "UTF-8") + "&brief=" + objectCode + "&tags=" + classId1 + "," + classId2;
        return uploadImageToBaidu(requestBody, objectCode, objectName, classId1, classId2);
    }

    @Override
    public ExternalArtifactDO getArtifact(Integer id) {
        return artifactMapper.selectOne(ExternalArtifactDO::getId, id);
    }


    @Transactional
    @Override
    public List<String> deleteTemplateImageAndArtifact(String objectCode, boolean delArtifact) throws IOException {
        List<String> contSignList = baiduAiImageService.getContSignListByObjectCode(objectCode);
        RateLimiter rateLimiter = RateLimiter.create(2.0); // 限流控制，每秒2个请求
        List<String> results = new ArrayList<>();
        for (String cs : contSignList) {
            rateLimiter.acquire();
            Map<String, Object> resultMap = deleteTemplateImage(cs);
            if (JObjectUtil.isNotEmpty(resultMap.get("error"))) {
                throw new RuntimeException("删除失败: " + cs); // 抛出异常触发回滚
            }
            String contSign = stringValue(resultMap.get("contSign"));
            String logId = stringValue(resultMap.get("logId"));
            results.add("删除图片成功，cont_sign为：" + contSign + "，log_id为：" + logId);
        }
        if (delArtifact) {
            int status = JObjectUtil.objectToInt(artifactService.deleteArtifact(objectCode).get("status"));
            if (status == 10658) {
                throw new BusinessException("百度图库中删除出现错误！");
            }
        }
        return results;
    }

    @Override
    public PageResult<ArtifactRespVO> selectPage(ArtifactQueryVO queryVO) {
        return artifactMapper.selectPage(queryVO);
    }

    @Override
    @Transactional
    public Boolean updateArtifact(ArtifactCreateVO saveVO) throws IOException {
        Integer artifactId = saveVO.getId();
        if (isEmpty(artifactId)) throw new BusinessException("未传入id！");
        ExternalArtifactDO externalArtifactDO = artifactMapper.selectOne(ExternalArtifactDO::getId, artifactId);
        String objectCode = externalArtifactDO.getCode();
        externalArtifactDO.setCode(saveVO.getCode());
        externalArtifactDO.setName(saveVO.getName());
        artifactMapper.updateById(externalArtifactDO);
        List<ExternalBaiduAiImageDO> baiduAiImageList = baiduAiImageService.getBaiduAiImageByObjectCode(objectCode);
        RateLimiter rateLimiter = RateLimiter.create(2.0); // 限流控制，每秒2个请求
        for (ExternalBaiduAiImageDO aiImage : baiduAiImageList) {
            aiImage.setCode(saveVO.getCode());
            aiImage.setClassId1(saveVO.getClassId1());
            aiImage.setClassId2(saveVO.getClassId2());
            int i = baiduAiImageMapper.updateById(aiImage);
            if (i != 1) {
                throw new BusinessException("更新失败！请检查");
            }
            rateLimiter.acquire();
            // 1. 构建表单参数
            FormBody.Builder formBuilder = new FormBody.Builder();
            formBuilder.add("cont_sign", aiImage.getContSign()); // 添加 cont_sign 参数
            formBuilder.add("brief", saveVO.getCode());           // 添加 brief 参数
            formBuilder.add("tags", saveVO.getClassId1() + "," + saveVO.getClassId2()); // 添加 tags 参数
            RequestBody body = formBuilder.build(); // 生成表单格式的 RequestBody
            Request request = new Request.Builder()
                    .url(IMAGE_UPDATE_URL)
                    .post(body)
                    .build();
            OkHttpClient client = HttpUtils.getClient();
            try (Response response = client.newCall(request).execute()) {
                if (response.isSuccessful()) {
                    String responseBodyStr = response.body().string();
                    JSONObject responseJson = JSON.parseObject(responseBodyStr);

                } else {
                    throw new BusinessException("请求百度API出现错误，请检查");
                }
            }
        }
        return true;
    }


    private Map<String, Object> uploadImageToBaidu(String requestBody, String objectCode, String objectName, String classId1, String classId2) throws IOException {
        HttpURLConnection conn = (HttpURLConnection) IMAGE_ADD_URL.openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("Accept", "application/json");
        try (OutputStream os = conn.getOutputStream()) {
            os.write(requestBody.getBytes(StandardCharsets.UTF_8));
        }
        int responseCode = conn.getResponseCode();
        String responseStr;
        try (InputStream is = responseCode == HttpURLConnection.HTTP_OK
                ? conn.getInputStream()
                : conn.getErrorStream()) {
            responseStr = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)).lines().collect(Collectors.joining());
        }
        if (responseCode != HttpURLConnection.HTTP_OK) {
            throw new IOException("API请求失败: " + responseCode + " - " + responseStr);
        }
        Map<String, Object> responseMap = JObjectUtil.toMap(JSON.parse(responseStr));

        Map<String, Object> resultMap = new HashMap<>();
        if (JObjectUtil.isNotEmpty(responseMap.get("error_code"))) {
            Integer errorCode = JObjectUtil.toInteger(responseMap.get("error_code"));
            if (errorCode == 216202) {
                resultMap.put("error", 10656);
                return resultMap;
            } else if (errorCode.equals(216681)) {
                throw new BusinessException("图片已存在于图库中！");
            }
            resultMap.put("error", 10655);
            return resultMap;
        }
        String contSign = stringValue(responseMap.get("cont_sign"));

        //如果表中不存在该objectCode，则创建新的文物编码、文物名对应关系
        if (JObjectUtil.isEmpty(artifactMapper.selectByCode(objectCode))) {
            if (JObjectUtil.isEmpty(objectName)) {
                resultMap.put("error", 10654);
                return resultMap;
            }
            ExternalArtifact artifact = new ExternalArtifact();
            artifact.setName(objectName);
            artifact.setCode(objectCode);
            artifact.setCreator("admin");
            artifact.setUpdater("admin");
            artifactMapper.insert(artifact);
        }

        ExternalBaiduAiImage baiduAiImage = new ExternalBaiduAiImage();
        baiduAiImage.setContSign(contSign);
        baiduAiImage.setCode(objectCode);
        baiduAiImage.setClassId1(JObjectUtil.toInteger(classId1));
        baiduAiImage.setClassId2(JObjectUtil.toInteger(classId2));
        baiduAiImage.setCreator("admin");
        baiduAiImage.setUpdater("admin");
        log.info(baiduAiImage.getCreator() + "添加了一张图片,cont_sign为:" + contSign);
        baiduAiImageMapper.insert(baiduAiImage);
        resultMap.put("objectCode", objectCode);
        resultMap.put("contSign", contSign);
        return resultMap;
    }

    private Map<String, Object> deleteTemplateImage(String contSign) throws IOException {
        Map<String, Object> resultMap = new HashMap<>();
        HttpURLConnection conn = (HttpURLConnection) IMAGE_DELETE_URL.openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("Accept", "application/json");
        String requestBody = "cont_sign=" + contSign;
        try (OutputStream os = conn.getOutputStream()) {
            os.write(requestBody.getBytes(StandardCharsets.UTF_8));
        }
        int responseCode = conn.getResponseCode();
        String responseStr;
        try (InputStream is = responseCode == HttpURLConnection.HTTP_OK ? conn.getInputStream() : conn.getErrorStream()) {
            responseStr = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)).lines().collect(Collectors.joining());
        }
        Map<String, Object> responseMap = JObjectUtil.toMap(JSON.parse(responseStr));
        if (responseCode != HttpURLConnection.HTTP_OK || JObjectUtil.isNotEmpty(responseMap.get("error_code"))) {
            throw new IOException("API请求失败: " + responseCode + " - " + responseStr);
        }
        if (baiduAiImageMapper.deleteByContSign(contSign) == 0) {
            resultMap.put("error", 10657);
            return resultMap;
        }
        String logId = stringValue(responseMap.get("log_id"));
        log.info("删除图片成功，cont_sign为：" + contSign + "，log_id为：" + logId);
        resultMap.put("contSign", contSign);
        resultMap.put("logId", logId);
        return resultMap;
    }


}
